#ifndef CONTROL_COMMAND_DISPATCHER_H_INCLUDED
#define CONTROL_COMMAND_DISPATCHER_H_INCLUDED

#include <control_dispatcher.h>
#include <control_terminal.h>

#include <cstdio>
#include <cerrno>
#include <unistd.h>

#include <utils/system_exception.h>

class ControlTerminal::CommandDispatcher
    : public ControlDispatcher
{
public:
    CommandDispatcher()
        : fd_(::fileno(stdin))
    {
        if(fd_ < 0)
        {
            throw utils::system_exception(errno);
        }
    }

    /*virtual*/
    bool dispatch(ControlTerminal & term)
    {
        char comm[256];

        int const r = ::read(fd_, comm, sizeof(comm));
        if(r < 0)
        {
            throw utils::system_exception(errno);
        }
        else if(r > 1)
        {
            return term.onCommand(comm, comm[r - 1] != '\n'
                                            ? (::fputc('\n', stdout), r)
                                            : (r - 1));
        }
        return true;
    }

    int fd() const
    {
        return fd_;
    }

    /*virtual*/
    ~CommandDispatcher() throw()
    { }

private:
    int const fd_;
};

#endif // CONTROL_COMMAND_DISPATCHER_H_INCLUDED
